﻿using Blog.Core.Domain.Model;
using Blog.Core.EFcore;
using Blog.Core.IServices;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;//日志记录
using System.Diagnostics;//秒表
using System.Text;

namespace Blog.Core.Api.Middleware
{
    /// <summary>
    /// 请求日志中间件
    /// </summary>
    public class RequestLogMiddleware
    {

        //下一个请求委托
        private readonly RequestDelegate _next;
        private readonly IServiceProvider serviceProvider;
        private readonly ILogger<RequestLogMiddleware> _logger; //记录日志
        private const string LOGIN_PATH = @"/api/User/UserLogin";//登录api的请求路径
                                                                 //构造方法进行依赖注入
        public RequestLogMiddleware(RequestDelegate next,
        ILogger<RequestLogMiddleware> logger, IServiceProvider serviceProvider)
        {
            _next = next;
            _logger = logger;
            this.serviceProvider = serviceProvider;
        }
        /// <summary>
        /// 公开方法
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public async Task InvokeAsync(HttpContext context)
        {
            var headers = context.Request.Headers;//请求头部
            var body = context.Request.Body;//请求身体
            var method = context.Request.Method;//请求方式
            var path = context.Request.Path;//请求路径
            var accesToken = context.Request.Headers["Authorization"];
            HttpRequest request = context.Request;
            string data = string.Empty;
            request.EnableBuffering();//启用缓存
            using (StreamReader reader = new StreamReader(request.Body, Encoding.UTF8, true, 1024, true))
            {
                data = await reader.ReadLineAsync();
                request.Body.Position = 0;
            }
            string username = context.User.FindFirst("UName")?.Value;
            if (string.IsNullOrEmpty(username))
            {
                username = "小豪";
            }
            try
            {
                #region 计时器记录运行时长
                Stopwatch stopwatch = new Stopwatch();
                stopwatch.Start();
                await _next(context); //调用下一个请求委托
                stopwatch.Stop();
                string requestUrl = context.Request.Path;
                _logger.LogInformation($"请求{requestUrl}，消耗了{stopwatch.ElapsedMilliseconds} 毫秒");//运行耗时
                #endregion
                //获取操作日志的应用服务对象
                IlogRecordIService ilogRecordIService = serviceProvider.GetRequiredService<IlogRecordIService>();
                //判读用户请求是否是登录
                if (path.ToString().ToLower() == LOGIN_PATH)
                {
                    Journal jour = new Journal
                    {
                        Createtimes = DateTime.Now,//创建时间
                        Use = "小豪",//应用
                        Classify = "登录日志",
                        Whether = false,//是否异常
                        Content = "用户登录，操作耗时：" + requestUrl,//内容
                        Module = path,
                        Operatorname = username
                    };
                    ilogRecordIService.LogAdd(jour);
                }
                else
                {
                    Journal jour = new Journal
                    {
                        Createtimes = DateTime.Now,//创建时间
                        Use = "小豪",//应用
                        Classify = "登录日志",
                        Whether = true,//是否异常
                        Content = "用户访问，操作耗时：" + requestUrl,//内容
                        Module = path,
                        Operatorname = username
                    };
                    ilogRecordIService.LogAdd(jour);
                }
            }
            catch (Exception ex)
            {
                //异常日志记录到文件
                _logger.LogError($"请求异常：{path},错误信息：{ex.Message}");

            }

        }
    }
}
